package com.sec.android.app.myfiles.thumbnail;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.util.chain.Chain;

import java.io.FileDescriptor;

public abstract class ThumbnailImp implements Chain<ThumbnailImp> {
    private static final String TAG = "ThumbnailImp";
    public static final int THUMBNAIL_SIZE = 320;

    protected Context mContext;

    private ThumbnailImp mNext;

    public ThumbnailImp(Context context) {
        mContext = context;
    }

    @Override
    public void setNext(ThumbnailImp next) {
        mNext = next;
    }

    public Bitmap createThumbnail(FileRecord record) {
        return createThumbnail(record, THUMBNAIL_SIZE);
    }

    public Bitmap createThumbnail(FileRecord record, int thumbnailSize) {
        Bitmap ret = null;

        try {
            if (record != null) {
                if (isSupport(record)) {
                    Bitmap bmp = _createThumbnail(record, thumbnailSize);

                    if (bmp != null && (bmp.getWidth() != thumbnailSize || bmp.getHeight() != thumbnailSize)) {
                        ret = getSizedCenterCropBmp(bmp, thumbnailSize);
                        bmp.recycle();
                    } else {
                        ret = bmp;
                    }

                } else if (mNext != null) {
                    ret = mNext.createThumbnail(record, thumbnailSize);
                }
            }

        } catch (OutOfMemoryError e) {
            Log.e(this, "OutOfMemoryError:" + e.toString());
        } catch (IllegalArgumentException e) {
            Log.e(this, "IllegalArgumentException:" + e.toString());
        }

        return ret;
    }

    private static Bitmap getSizedCenterCropBmp(Bitmap bmpSrc, int nSize) throws OutOfMemoryError {
        Bitmap croppedBitmap = null;

        if (bmpSrc != null) {
            Bitmap scaledBitmap = null;
            try {
                if (bmpSrc.getWidth() > bmpSrc.getHeight()) {
                    int scaled = (int) ((float) bmpSrc.getWidth() / (float) bmpSrc.getHeight() * (float) nSize);
                    scaledBitmap = Bitmap.createScaledBitmap(bmpSrc, scaled, nSize, true);
                    if (scaledBitmap != null) {
                        croppedBitmap = Bitmap.createBitmap(scaledBitmap, scaledBitmap.getWidth() / 2 - scaledBitmap.getHeight() / 2, 0,
                                scaledBitmap.getHeight(), scaledBitmap.getHeight());
                        scaledBitmap.recycle();
                    }
                } else {
                    int scaled = (int) ((float) bmpSrc.getHeight() / (float) bmpSrc.getWidth() * (float) nSize);
                    scaledBitmap = Bitmap.createScaledBitmap(bmpSrc, nSize, scaled, true);
                    if (scaledBitmap != null) {
                        croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, scaledBitmap.getHeight() / 2 - scaledBitmap.getWidth() / 2,
                                scaledBitmap.getWidth(), scaledBitmap.getWidth());

                        scaledBitmap.recycle();
                    }
                }
            } catch (NullPointerException e) {
                Log.e(TAG, "NullPointerException:" + e.toString());
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "IllegalArgumentException:" + e.toString());
            }
        }

        return croppedBitmap;
    }

    public boolean isSupportType(FileRecord record) {
        boolean bRet = false;
        if (record != null) {
            if (isSupport(record)) {
                bRet = true;
            } else {
                if (mNext != null) {
                    bRet = mNext.isSupportType(record);
                }
            }
        }
        return bRet;
    }


    public static BitmapFactory.Options getBmpFactoryOption(FileDescriptor fd, int thumbnailSize) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 1;
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFileDescriptor(fd, null, options);

        if (options.mCancel || options.outWidth == -1 || options.outHeight == -1) {
            return null;
        }
        // Determine how much to scale down the image
        options.inSampleSize = calculateInSampleSize(options, thumbnailSize, thumbnailSize);
        options.inJustDecodeBounds = false;
        options.inPreferQualityOverSpeed = false;
        //options.semIsPreview = true;
        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return options;
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    protected abstract boolean isSupport(FileRecord record);

    protected abstract Bitmap _createThumbnail(FileRecord record, int thumbnailSize);
}
